export interface FormColumn<P = string> {
  /**
   * 表单项的key
   */
  key: keyof P
  vShow?: boolean

  actions?: any[]

  component?:
    | 'Input'
    | 'Select'
    | 'RadioGroup'
    | 'CheckboxGroup'
    | 'Upload'
    | 'Textarea'
    | 'Switch'

  rule?: RuleItem | RuleItem[]

  required?: boolean

  formItemProps: FormItemProps

  componentProps: ComponentProps

  componentSlot?: string

  slot?: string
}

type RuleType =
  | 'string'
  | 'number'
  | 'boolean'
  | 'method'
  | 'regexp'
  | 'integer'
  | 'float'
  | 'array'
  | 'object'
  | 'enum'
  | 'date'
  | 'url'
  | 'hex'
  | 'email'
  | 'any'

type Trigger = 'change' | 'blur' | Array<'change' | 'blur'>

interface ValidateCallback {
  (error?: string | Error): void
}

interface RuleItem {
  type?: RuleType
  required?: boolean
  message?: string
  trigger?: Trigger
  pattern?: RegExp
  min?: number
  max?: number
  len?: number
  enum?: any[]
  whitespace?: boolean
  transform?: (value: any) => any
  validator?: (rule: RuleItem, value: any, callback: ValidateCallback) => boolean | string
  asyncValidator?: (
    rule: RuleItem,
    value: any,
    callback: ValidateCallback,
  ) => void
}

export type Rules = Record<string, RuleItem | RuleItem[]>

export type DynamicForm<T = Record<string, any>> = FormColumn<T>[]

type FormValidateCallback = (errors: any[]) => void

export interface FormInstance extends UvFormInstance {
  setFormValues: (values: Record<string, any>) => void
  getFormValues: () => Record<string, any>
  getFormValuesWithValid: () => Promise<void | Record<string, any>>
  submit: () => void
}

export interface UvFormInstance {
  /** 对整个表单进行校验的方法 */
  validate: () => Promise<void>
  /** 如果rules中有自定义方法等，需要用此方法设置rules规则 */
  setRules: (rules: any) => void
  /** 对部分表单字段进行校验，回调返回错误，需要自定义后续逻辑 */
  validateField: (
    field: string | string[],
    callback?: FormValidateCallback,
  ) => void
  /** 对整个表单进行重置，将所有字段值重置为初始值并移除校验结果 */
  resetFields: () => void
  /** 清空校验结果 */
  clearValidate: (props?: string | string[]) => void
}

export interface FormItemProps {
  label?: string
  prop?: string
  borderBottom?: string | boolean
  labelWidth?: string | number
  labelPosition?: 'left' | 'top'
  leftIcon?: string
  leftIconStyle?: string | object
  required?: boolean
  customStyle?: object
  onBlur?: (value: any) => void
  onChange?: (value: any) => void
  borderColor?: string
}

export type ComponentProps = {
  placeholder?: string
  disabledColor?: string
  disabled?: boolean
  options?: any[]
  border?: string
  suffixText?: string
} & Record<string, any>

export const createInputFormItem = ({
  label,
  placeholder,
  labelWidth,
  type,
}: {
  label: string
  placeholder: string
  labelWidth?: string
  type?: string
}): {
  componentProps: ComponentProps
  formItemProps: FormItemProps
} => ({
  componentProps: {
    placeholder,
    type: type || 'text',
    prefixIconStyle: 'font-size: 24rpx; color: #ccc',
    customStyle: {
      backgroundColor: '#EFEFEF',
      height: '90rpx',
      border: 'none',
      borderRadius: '16rpx',
    },
  },
  formItemProps: {
    label,
    labelWidth: labelWidth || '160rpx',
    customStyle: {
      fontSize: '28rpx',
    },
  },
})

export const createInputRule = (
  msg: string = '',
  other?: Partial<RuleItem>,
): { rule: RuleItem } => ({
  rule: {
    type: 'string',
    required: true,
    message: msg,
    trigger: ['blur', 'change'],
    ...(other || {}),
  },
})
